package me.sealer.ssm.aspect;

import lombok.extern.slf4j.Slf4j;
import me.sealer.ssm.constant.Dict;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;

/**
 * @author sealer
 * @date 2016/09/30
 * <p>
 * 在service包中定义的任意方法的执行：
 * execution（* com.xyz.service.*.*（..））
 * 在service包或其子包中定义的任意方法的执行：
 * execution（* com.xyz.service..*.*（..））
 */
@Slf4j
@Aspect
@Component
public class LogAspect {
    /**
     * 开始时间
     */
    private long startTimeMillis = 0;
    /**
     * 结束时间
     */
    private long endTimeMillis = 0;

    /**
     * 切面target签名
     */
    private String targetSignature;

    /**
     * Pointcut
     * 定义Pointcut，Pointcut的名称为aspectjMethod()，此方法没有返回值和参数
     * 该方法就是一个标识，不进行调用
     */
    @Pointcut("execution(* me.sealer.ssm.controller..*.*(..))")
    private void aspectjController() {
    }

    /**
     * 方法调用前触发 记录开始时间
     *
     * @author sealer
     * @date 2016年9月30日13:03:18
     * <p>
     * 亦可写作如下:
     * <code>@Before(value = "execution(* me.sealer.ssm.controller..*.*(..))")</code>
     * </p>
     */
    @Before(value = "aspectjController()")
    public void doBeforeInControllerLayer() {
        // 记录方法开始执行的时间
        startTimeMillis = System.currentTimeMillis();
    }

    /**
     * 方法调用后触发 记录结束时间
     *
     * @param joinPoint 连接点
     * @author sealer
     * @date 2016年9月30日13:03:12
     */
    @After(value = "aspectjController()")
    public void doAfterInControllerLayer(JoinPoint joinPoint) {
        targetSignature = joinPoint.getSignature().toLongString();
        // 记录方法执行完成的时间
        endTimeMillis = System.currentTimeMillis();
        this.printOperationTimeLog();
    }

    @AfterReturning(value = "aspectjController()", returning = "ret")
    public void doAfterReturningControllerLayer(JoinPoint joinPoint, Object ret) {
    }

    /**
     * 输出日志
     *
     * @author sealer
     * @date 2016年9月30日13:02:59
     */
    private void printOperationTimeLog() {
        String startTime = new SimpleDateFormat(Dict.YYYY_MM_DD_HH_MM_SS_SSS).format(startTimeMillis);
        String endTime = new SimpleDateFormat(Dict.YYYY_MM_DD_HH_MM_SS_SSS).format(endTimeMillis);
        if (log.isDebugEnabled()) {
            log.debug(targetSignature + ": start_time：" + startTime + ", end_time：" + endTime + ", cost_time: " + (endTimeMillis - startTimeMillis) + "ms.");
        }
    }
}
